@file:Suppress("PrivatePropertyName")

package com.jxpanda.plugin.initializr.config

import com.baomidou.mybatisplus.generator.config.po.TableInfo
import com.jxpanda.plugin.initializr.toolkit.StringKit

private val REGEX_RE_PREFIX = Regex("RE[{\\[]+")
private val REGEX_RE_SUFFIX = Regex("[}\\]]")
private val REGEX_REDUNDANCY = Regex("$REGEX_RE_PREFIX[\\w|.]*$REGEX_RE_SUFFIX")
private val REGEX_ENUM = Regex("ENUM[(（][a-zA-Z0-9|_\\u4e00-\\u9fa5,，]*[)）]")
private val REGEX_ENUM_VALUE = Regex("\\d+\\|\\w+\\|[\\u4e00-\\u9fa5,，]+(?<![,，])")


private const val ENUM_PREFIX = "ENUM"

private const val CFG_KEY_ENUM = "enum"
private const val CFG_KEY_HAS_ENUM = "hasEnum"

/**
 * 枚举注入器，从注释中读取枚举，注入到生成的文件中
 * */
class EnumInjector : InjectorConfig.Injector() {

    override fun buildInjectMap(tableInfo: TableInfo): Map<String, Any> {
        val parent = packageConfig.parent
        val enumMap = tableInfo.fields.filter { it.comment.contains(ENUM_PREFIX) }.associateBy({ it.name }, {
            EnumInfo.analyzeComment(it.comment, parent, it.propertyName)
        })
        return mapOf(
            CFG_KEY_ENUM to enumMap,
            CFG_KEY_HAS_ENUM to enumMap.filterValues { !it.redundancy }.isNotEmpty(),
            CFG_KEY_INJECT_PACKAGE to enumMap.filterValues { it.redundancy && !it.redundancyClass.contains(parent) }
                .map { it.value.redundancyClass })
    }


    /**
     * 解析枚举的数据对象
     * */
    data class EnumInfo(
        /**
         * 原注释
         * */
        val comment: String = "",
        /**
         * 需要同步冗余导入的类名，可以为空
         * */
        val redundancyClass: String = "",
        /**
         * 字段名
         * */
        val fieldType: String = "",
        /**
         * 值列表
         * */
        val values: List<EnumValue> = emptyList(),
        /**
         * 是否冗余
         * */
        val redundancy: Boolean = redundancyClass.isNotBlank()
    ) {

        companion object {
            fun analyzeComment(comment: String, parent: String, propertyName: String): EnumInfo {
                // 先匹配是否是冗余字段
                val findRedundancy = REGEX_REDUNDANCY.find(comment)?.value ?: ""
                return if (findRedundancy.isNotBlank()) {
                    val split = findRedundancy
                        .replace(REGEX_RE_PREFIX, "")
                        .replace(REGEX_RE_SUFFIX, "")
                        .split(".")
                    // 冗余过来的类名
                    val redundancyClassName = StringKit.camelCase(split[0]).capitalize()
                    // 冗余过来的字段类型
                    val redundancyTypeName = StringKit.camelCase(split[1]).capitalize()
                    EnumInfo(
                        comment,
                        "${parent}.${redundancyClassName}",
                        "${redundancyClassName}.${redundancyTypeName}",
                        emptyList()
                    )
                } else {
                    val enumString = REGEX_ENUM.find(comment)?.value ?: ""
                    val enumValueList = REGEX_ENUM_VALUE.findAll(enumString).toList().mapNotNull { match ->
                        val value = match.value
                        if (value.isBlank() || value == "ENUM") {
                            null
                        } else {
                            val split = value.split("|")
                            EnumValue(split[1].toUpperCase(), split[0].toInt(), split[2])
                        }
                    }
                    EnumInfo(comment, "", propertyName.capitalize(), enumValueList)
                }
            }
        }

    }

    data class EnumValue(
        /**
         * 枚举值的名称
         * */
        val field: String,
        /**
         * 枚举值的值
         * */
        val value: Int,
        /**
         * 描述
         * */
        val description: String
    )


}